home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / C and C++ / Gnuplot 3.5 for Macintosh / SOURCES 3.5 / binary.c < prev    next >
Text File  |  1993-11-12  |  15KB  |  550 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: binary.c%v 3.50.1.16 1993/08/27 05:04:42 woo Exp $";
  3. #endif
  4.  
  5. /*
  6.  * The addition of gnubin and binary, along with a small patch
  7.  * to command.c, will permit gnuplot to plot binary files.
  8.  * gnubin  - contains the code that relies on gnuplot include files
  9.  *                     and other definitions
  10.  * binary      - contains those things that are independent of those 
  11.  *                     definitions and files
  12.  *
  13.  * With these routines, hidden line removal of your binary data is possible!
  14.  *
  15.  * Last update:  3/29/92 memory allocation bugs fixed. jvdwoude@hut.nl
  16.  *               3/09/92 spelling errors, general cleanup, use alloc with no
  17.  *                       nasty fatal errors
  18.  *               3/03/92 for Gnuplot 3.24.
  19.  * Created from code for written by RKC for gnuplot 2.0b.
  20.  *
  21.  * Copyright (c) 1991,1992 Robert K. Cunningham, MIT Lincoln Laboratory
  22.  *
  23.  */
  24. #include <stdio.h>
  25. #if !defined(apollo) && !defined(sequent) && !defined(u3b2) && !defined(alliant) &&!defined(sun386)
  26. #include <stdlib.h> /* realloc() */
  27. #else
  28. #include <sys/types.h> /* typedef long size_t; */
  29. extern char *realloc();
  30. #endif
  31. #include <math.h>
  32.  
  33. #if defined(MSDOS) && defined(__TURBOC__) && !defined(DOSX286)
  34. #include <alloc.h>        /* for farmalloc, farrealloc */
  35. #define SMALLMALLOC
  36. #endif
  37. #if defined(_Windows) && !defined(WIN32)
  38. #include <windows.h>
  39. #include <windowsx.h>
  40. #define farmalloc(s) GlobalAllocPtr(GHND,s)
  41. #define farrealloc(p,s) GlobalReAllocPtr(p,s,GHND)
  42. #define SMALLMALLOC
  43. #endif
  44. #ifdef sequent
  45. #include <sys/types.h>      /* unsigned long size_t; */
  46. #endif
  47.  
  48. #include "plot.h"   /* We have to get TRUE and FALSE */
  49. #ifdef THINK_C
  50. #include "tout_protos.h"
  51. #endif
  52.  
  53. float GPFAR *vector();
  54. float GPFAR *extend_vector();
  55. float GPFAR *retract_vector();
  56. float GPFAR * GPFAR *matrix();
  57. float GPFAR * GPFAR *extend_matrix();
  58. float GPFAR * GPFAR *retract_matrix();
  59. void free_matrix();
  60. void free_vector();
  61.  
  62. /* versions of alloc, realloc and free that work with segmented
  63.    architectures (yuk!) */
  64. char GPFAR *
  65. gpfaralloc(size, message)
  66.     unsigned long size;        /* # of bytes */
  67.     char *message;            /* description of what is being allocated */
  68. {
  69. #ifdef SMALLMALLOC
  70.     char GPFAR *p;                /* the new allocation */
  71.     char errbuf[100];        /* error message string */
  72.     p = farmalloc(size);
  73.     if (p == (char *)NULL) {
  74.         /* really out of memory */
  75.         if (message != NULL) {
  76.             (void) sprintf(errbuf, "out of memory for %s", message);
  77.             int_error(errbuf, NO_CARET);
  78.             /* NOTREACHED */
  79.         }
  80.         /* else we return NULL */
  81.     }
  82.     return(p);
  83. #else
  84.  
  85. #ifdef THINK_C
  86.     char GPFAR *p;                /* the new allocation */
  87.     p = (char GPFAR *) alloc(size, message);
  88.     return (p);
  89. #else
  90.     return alloc(size, message);
  91. #endif
  92. #endif
  93. }
  94.  
  95. char GPFAR *
  96. gpfarrealloc(p, size)
  97.     char GPFAR *p;            /* old pointer */
  98.     unsigned long size;        /* # of bytes */
  99. {
  100. #ifdef SMALLMALLOC
  101.     return farrealloc(p, size);
  102. #else
  103.  
  104. #ifdef THINK_C
  105.     char GPFAR *p2;
  106.     p2 = (char GPFAR *) realloc((void *)p, (size_t)size);
  107.     return (p2);
  108. #else
  109.     return realloc(p, (size_t)size);
  110. #endif
  111.  
  112. #endif
  113. }
  114.  
  115. void
  116. gpfarfree(p)
  117. char GPFAR *p;
  118. {
  119. #ifdef SMALLMALLOC
  120. #ifdef _Windows
  121. HGLOBAL hGlobal = GlobalHandle(SELECTOROF(p));
  122.     GlobalUnlock(hGlobal);
  123.     GlobalFree(hGlobal);
  124. #else
  125.     farfree(p);
  126. #endif
  127. #else
  128.  
  129. #ifdef THINK_C
  130.     free((void *)p);
  131. #else
  132.     free(p);
  133. #endif
  134.     
  135. #endif
  136. }
  137.  
  138.  
  139. /* 
  140.  * This routine scans the first block of the file to see if the file is a 
  141.  * binary file.  A file is considered binary if 10% of the characters in it 
  142.  * are not in the ascii character set. (values < 128), or if a NUL is found.
  143.  * I hope this doesn't break when used on the bizzare PC's.
  144.  */
  145. int
  146.   is_binary_file(fp)
  147. register FILE *fp;
  148. {
  149.   register int i,len;
  150.   register int odd;                /* Contains a count of the odd characters */
  151.   long where;
  152.   register unsigned char *c;
  153.   unsigned char buffer[512];
  154.  
  155.   if((where = ftell(fp)) == -1){ /* Find out where we start */
  156.     fprintf(stderr,"Notice: Assuming unseekable data is not binary\n");
  157.     return(FALSE);
  158.   }
  159.   else {
  160.     rewind(fp);
  161.  
  162.     len = fread(buffer,sizeof(char),512,fp);
  163.     if (len <= 0)                      /* Empty file is declared ascii */
  164.       return(FALSE);
  165.  
  166.     c = buffer;
  167.  
  168.     /* now scan buffer to look for odd characters */
  169.     odd = 0;
  170.     for (i=0; i<len; i++,c++) {
  171.       if (!*c) {              /* NUL _never_ allowed in text */
  172.     odd += len;
  173.     break;
  174.       }
  175.       else if ((*c & 128) ||/* Meta-characters--we hope it's not formatting */
  176.            (*c == 127)|| /* DEL */
  177.            (*c < 32 && 
  178.         *c != '\n' && *c != '\r' && *c != '\b' &&
  179.         *c != '\t' && *c != '\f' && *c != 27 /*ESC*/))
  180.     odd++;
  181.     }
  182.   
  183.     fseek(fp,where,0); /* Go back to where we started */
  184.  
  185.     if (odd * 10 > len)             /* allow 10% of the characters to be odd */
  186.       return(TRUE);
  187.     else
  188.       return(FALSE);
  189.   }
  190. }
  191. /*========================= I/O Routines ================================
  192.   These may be useful for situations other than just gnuplot.  Note that I 
  193.   have included the reading _and_ the writing routines, so others can create 
  194.   the file as well as read the file.
  195. */
  196.  
  197. /*
  198.   This function reads a matrix from a stream
  199.  
  200.   This routine never returns anything other than vectors and arrays
  201.   that range from 0 to some number.  
  202.  
  203. */
  204. #define START_ROWS 100/* Each of these must be at least 1 */
  205. #define ADD_ROWS 50
  206. int
  207.   fread_matrix(fin,ret_matrix,nr,nc,row_title,column_title)
  208. FILE *fin;
  209. float GPFAR * GPFAR * GPFAR *ret_matrix,GPFAR * GPFAR * row_title, GPFAR * GPFAR *column_title;
  210. int *nr,*nc;
  211. {
  212.   float  GPFAR * GPFAR *m, GPFAR *rt, GPFAR *ct;
  213.   register int num_rows = START_ROWS;
  214.   register int num_cols;
  215.   register int current_row = 0;
  216.   register float  GPFAR * GPFAR *temp_array;
  217.   float fdummy;
  218.   
  219.   fread(&fdummy,sizeof(fdummy),1,fin);
  220.   num_cols = (int)fdummy;
  221.   
  222.   /* 
  223.     Choose a reasonable number of rows,
  224.     allocate space for it and continue until this space
  225.     runs out, then extend the matrix as necessary.
  226.     */
  227.   ct = vector(0,num_cols-1);
  228.   fread(ct,sizeof(*ct),num_cols,fin);
  229.  
  230.   rt = vector(0,num_rows-1);
  231.   m = matrix(0,num_rows-1,0,num_cols-1);
  232.  
  233.   while(fread(&rt[current_row], sizeof(rt[current_row]), 1, fin)==1){ 
  234.     /* We've got another row */
  235.     if(fread(m[current_row],sizeof(*(m[current_row])),num_cols,fin)!=num_cols)
  236.       return(FALSE);      /* Not a True matrix */
  237.  
  238.     current_row++;
  239.     if(current_row>=num_rows){ /* We've got to make a bigger rowsize */
  240.       temp_array = extend_matrix(m,0,num_rows-1,0,num_cols-1,
  241.                  num_rows+ADD_ROWS-1,num_cols-1);
  242.       rt = extend_vector(rt,0,num_rows-1,num_rows+ADD_ROWS-1);
  243.       
  244.       num_rows+= ADD_ROWS;
  245.       m = temp_array;
  246.     }
  247.   }
  248.   /*  finally we force the matrix to be the correct row size */
  249.   /*  bug fixed. procedure called with incorrect 6th argument. jvdwoude@hut.nl */
  250.   temp_array = retract_matrix(m,0,num_rows-1,0,num_cols-1,current_row-1,num_cols-1);
  251.   /* Now save the things that change */
  252.   *ret_matrix = temp_array;
  253.   *row_title = retract_vector(rt, 0, num_rows-1, current_row-1);
  254.   *column_title = ct;
  255.   *nr = current_row;/* Really the total number of rows */
  256.   *nc = num_cols;
  257.   return(TRUE);
  258. }
  259.  
  260. /* This writes a matrix to a stream 
  261.    Note that our ranges are inclusive ranges--and we can specify subsets.
  262.    This behaves similarly to the xrange and yrange operators in gnuplot
  263.    that we all are familiar with.
  264. */
  265. int
  266.   fwrite_matrix(fout,m,nrl,nrh,ncl,nch,row_title,column_title)
  267. register FILE *fout;
  268. register float  GPFAR * GPFAR *m, GPFAR *row_title, GPFAR *column_title;
  269. register int nrl,nrh,ncl,nch;
  270. {
  271.   register int j;
  272.   float length;
  273.   register int col_length;
  274.   register int status;
  275.   float  GPFAR *title = NULL;
  276.  
  277.   length = col_length = nch-ncl+1;
  278.  
  279.   if((status = fwrite((char*)&length,sizeof(float),1,fout))!=1){
  280.     fprintf(stderr,"fwrite 1 returned %d\n",status);
  281.     return(FALSE);
  282.   }
  283.   
  284.   if(!column_title){
  285.     column_title = title = vector(ncl,nch);
  286.     for(j=ncl; j<=nch; j++)
  287.       title[j] = j;
  288.   }
  289.   fwrite((char*)column_title,sizeof(float),col_length,fout);
  290.   if(title){
  291.     free_vector(title,ncl,nch);
  292.     title = NULL;
  293.   }
  294.  
  295.   if(!row_title){
  296.     row_title = title = vector(nrl,nrh);
  297.     for(j=nrl; j<=nrh; j++)
  298.       title[j] = j;
  299.   }
  300.     
  301.   for(j=nrl; j<=nrh; j++){
  302.     fwrite((char*)&row_title[j],sizeof(float),1,fout);
  303.     fwrite((char*)(m[j]+ncl),sizeof(float),col_length,fout);
  304.   }
  305.   if(title)
  306.     free_vector(title,nrl,nrh);
  307.  
  308.   return(TRUE);
  309. }
  310.  
  311. /*===================== Support routines ==============================*/
  312.  
  313. /******************************** VECTOR *******************************
  314.  *       The following routines interact with vectors.
  315.  *
  316.  *   If there is an error we don't really return - int_error breaks us out.
  317.  *
  318.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  319.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  320.  *
  321.  */
  322. float GPFAR *vector(nl,nh)
  323.      register int nl,nh;
  324. {
  325.   register float GPFAR *vec;
  326.  
  327.   if (!(vec = (float GPFAR *)gpfaralloc((unsigned long) (nh-nl+1)*sizeof(float),NULL))){
  328.     int_error("not enough memory to create vector",NO_CARET);
  329.     return NULL;/* Not reached */
  330.   }
  331.   return (vec-nl);
  332. }
  333. /* 
  334.  *  Free a vector allocated above
  335.  *
  336.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  337.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  338.  *
  339.  */
  340. void 
  341.   free_vector(vec,nl,nh)
  342. float  GPFAR *vec;
  343. int nl,nh;
  344. {
  345.   gpfarfree((char GPFAR *)(vec+nl));
  346. }
  347. /************ Routines to modify the length of a vector ****************/  
  348. float  GPFAR *
  349.   extend_vector(vec,old_nl,old_nh,new_nh)
  350. float  GPFAR *vec;
  351. register int old_nl,old_nh,new_nh;
  352. {
  353.   register float  GPFAR *new_v;
  354.   if(!(new_v = (float GPFAR *)gpfarrealloc((void*)(vec+old_nl),
  355.                        (unsigned long)(new_nh-old_nl+1)*sizeof(float)) )){
  356.     int_error("not enough memory to extend vector",NO_CARET);
  357.     return NULL;
  358.   } 
  359.   return new_v-old_nl;
  360. }
  361.  
  362. float  GPFAR *
  363.   retract_vector(v,old_nl,old_nh,new_nh)
  364. float  GPFAR *v;
  365. register int old_nl,old_nh,new_nh;
  366. {
  367.   register float GPFAR *new_v;
  368.   if(!(new_v = (float GPFAR *)gpfarrealloc((void*)(v+old_nl),
  369.                                (unsigned long)(new_nh-old_nl+1)*sizeof(float)))){
  370.     int_error("not enough memory to retract vector",NO_CARET);
  371.     return NULL;
  372.   }
  373.   return new_v-old_nl;
  374. }
  375. /***************************** MATRIX ************************
  376.  *
  377.  *       The following routines work with matricies
  378.  *
  379.  *      I always get confused with this, so here I write it down:
  380.  *               for nrl<= nri <=nrh and
  381.  *               for ncl<= ncj <=nch
  382.  *  
  383.  *   This matrix is accessed as:
  384.  *   
  385.  *     matrix[nri][ncj];
  386.  *     where nri is the offset to the pointer to a vector where the
  387.  *     ncjth element lies.
  388.  * 
  389.  *   If there is an error we don't really return - int_error breaks us out.
  390.  *
  391.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  392.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  393.  *
  394.  */
  395. float 
  396.    GPFAR * GPFAR *matrix(nrl,nrh,ncl,nch)
  397. register int nrl,nrh,ncl,nch;
  398. {
  399.   register int i;
  400.   register float GPFAR * GPFAR *m;
  401.  
  402.   if (!(m = (float GPFAR * GPFAR *)gpfaralloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *),NULL))){
  403.     int_error("not enough memory to create matrix",NO_CARET);
  404.     return NULL;
  405.   }
  406.   m -= nrl;
  407.  
  408.   for (i=nrl; i<=nrh; i++)
  409.     {
  410.       if (!(m[i] = (float GPFAR *) gpfaralloc((unsigned long)(nch-ncl+1)*sizeof(float),NULL))){
  411.     free_matrix(m,nrl,i-1,ncl,nch);
  412.     int_error("not enough memory to create matrix",NO_CARET);
  413.     return NULL;
  414.       }
  415.       m[i] -= ncl;
  416.     }
  417.   return m;
  418. }
  419. /* 
  420.  * Free a matrix allocated above
  421.  *
  422.  *
  423.  *   This subroutine based on a subroutine listed in "Numerical Recipies in C",
  424.  *   by Press, Flannery, Teukoilsky and Vetterling (1988).
  425.  *
  426.  */
  427. void 
  428.   free_matrix(m,nrl,nrh,ncl,nch)
  429. float  GPFAR * GPFAR *m;
  430. unsigned nrl,nrh,ncl,nch;
  431. {
  432.   register int i;
  433.  
  434.   for (i=nrl; i<=nrh; i++) 
  435.     gpfarfree((char GPFAR *) (m[i]+ncl));
  436.   gpfarfree((char GPFAR *) (m+nrl));
  437. }
  438. /*
  439.   This routine takes a sub matrix and extends the number of rows and 
  440.   columns for a new matrix
  441. */
  442. float GPFAR * GPFAR *extend_matrix(a,nrl,nrh,ncl,nch,srh,sch)
  443.      register float  GPFAR * GPFAR *a;
  444.      register int nrl,nrh,ncl,nch;
  445.      register int srh,sch;
  446. {
  447.   register int i;
  448.   register float GPFAR * GPFAR *m;
  449.  
  450.   /*  bug fixed. realloc() called with incorrect 2nd argument. jvdwoude@hut.nl */
  451.   if(!(m = (float GPFAR * GPFAR *)gpfarrealloc((void*)(a+nrl),(unsigned long)(srh-nrl+1)*sizeof(float GPFAR *)) )){
  452.     int_error("not enough memory to extend matrix",NO_CARET);
  453.     return NULL;
  454.   }
  455.  
  456.   m -= nrl;
  457.  
  458.   if(sch != nch){
  459.     for(i=nrl; i<=nrh; i++)
  460.       {/* Copy and extend rows */
  461.     if(!(m[i] = extend_vector(m[i],ncl,nch,sch))){
  462.       free_matrix(m,nrl,nrh,ncl,sch);
  463.       int_error("not enough memory to extend matrix",NO_CARET);
  464.       return NULL;
  465.     }
  466.       }
  467.   }
  468.   for(i=nrh+1; i<=srh; i++)
  469.     {
  470.       if(!(m[i] = (float GPFAR *) gpfaralloc((unsigned long) (nch-ncl+1)*sizeof(float),NULL))){
  471.     free_matrix(m,nrl,i-1,nrl,sch);
  472.     int_error("not enough memory to extend matrix",NO_CARET);
  473.     return NULL;
  474.       }
  475.       m[i] -= ncl;
  476.     }
  477.   return m;
  478. }
  479. /*
  480.   this routine carves a large matrix down to size
  481. */
  482. float GPFAR * GPFAR *retract_matrix(a,nrl,nrh,ncl,nch,srh,sch)
  483.      register float  GPFAR * GPFAR *a;
  484.      register int nrl,nrh,ncl,nch;
  485.      register int srh,sch;
  486. {
  487.   register int i;
  488.   register float  GPFAR * GPFAR *m;
  489.  
  490.   for(i=srh+1; i<=nrh; i++) {
  491.     free_vector(a[i],ncl,nch);
  492.   }
  493.  
  494.   /*  bug fixed. realloc() called with incorrect 2nd argument. jvdwoude@hut.nl */
  495.   if(!(m = (float GPFAR * GPFAR *)gpfarrealloc((void*)(a+nrl), (unsigned long)(srh-nrl+1)*sizeof(float GPFAR *)) )){
  496.     int_error("not enough memory to retract matrix",NO_CARET);
  497.     return NULL;
  498.   }
  499.  
  500.   m -= nrl;
  501.  
  502.   if(sch != nch){
  503.     for(i=nrl; i<=srh; i++)       
  504.     if(!(m[i] = retract_vector(m[i],ncl,nch,sch))){ {/* Shrink rows */
  505.       free_matrix(m,nrl,srh,ncl,sch);
  506.       int_error("not enough memory to retract matrix",NO_CARET);
  507.       return NULL;
  508.     }
  509.       }
  510.   }
  511.  
  512.   return m;
  513. }
  514.  
  515. float 
  516.    GPFAR * GPFAR *convert_matrix(a,nrl,nrh,ncl,nch)
  517. float GPFAR *a;
  518. register int nrl,nrh,ncl,nch;
  519.  
  520. /* allocate a float matrix m[nrl...nrh][ncl...nch] that points to the
  521. matrix declared in the standard C manner as a[nrow][ncol], where 
  522. nrow=nrh-nrl+1, ncol=nch-ncl+1.  The routine should be called with
  523. the address &a[0][0] as the first argument.  This routine does
  524. not free the memory used by the original array a but merely assigns
  525. pointers to the rows. */
  526.  
  527. {
  528.   register int i,j,ncol,nrow;
  529.   register float GPFAR * GPFAR *m;
  530.  
  531.   nrow=nrh-nrl+1;
  532.   ncol=nch-ncl+1;
  533.   if (!(m = (float GPFAR * GPFAR *)gpfaralloc((unsigned long)(nrh-nrl+1)*sizeof(float GPFAR *),NULL))){
  534.       int_error("allocation failure in convert_matrix()",NO_CARET);
  535.       return NULL;
  536.   }
  537.   m -= nrl;
  538.  
  539.   m[nrl]=a-ncl;
  540.   for(i=1,j=nrl+1;i<=nrow-1;i++,j++) m[j]=m[j-1]+ncol;
  541.   return m;
  542. }
  543.  
  544. void free_convert_matrix(b,nrl,nrh,ncl,nch)
  545. float GPFAR* GPFAR *b;
  546. register int nrl,nrh,ncl,nch;
  547. {
  548.     free((char*) (b+nrl));
  549. }
  550.